package com.jeasonzhao.commons.db.helper;

import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Vector;

import com.jeasonzhao.commons.utils.Algorithms;
import com.jeasonzhao.commons.utils.ResourceException;
import com.jeasonzhao.commons.xml.XMLException;
import com.jeasonzhao.commons.xml.XMLHelper;
import com.jeasonzhao.commons.xml.XMLNode;

public class ConnectionStringHelper
{
    private java.util.Vector<ConnectionStringInfo> m_allConnectionConfiguration = null;
    private static final ConnectionStringHelper m_instance = new ConnectionStringHelper();
    public static ConnectionStringHelper getInstance()
    {
        return m_instance;
    }

    private ConnectionStringHelper()
    {
        m_allConnectionConfiguration = new Vector<ConnectionStringInfo>();
        try
        {
            XMLNode node = XMLHelper.myConfiguration(ConnectionStringHelper.class);
            if(null == node)
            {
                return;
            }
            for(XMLNode nodeSet : node.selectNodes("dbms"))
            {
                String strNameGroup = nodeSet.subItemOrValueOf("name");
                String strDriver = nodeSet.subItemOrValueOf("driver");
                String strUrl = nodeSet.subItemOrValueOf("url");
                if(Algorithms.isEmpty(strDriver) || Algorithms.isEmpty(strNameGroup) || Algorithms.isEmpty(strUrl))
                {
                    continue;
                }
                for(String name : strNameGroup.split(","))
                {
                    m_allConnectionConfiguration.add(new ConnectionStringInfo(name,
                        strDriver,
                        strUrl));
                }
            }
        }
        catch(ResourceException ex)
        {
            ex.printStackTrace();
        }
        catch(XMLException ex)
        {
            ex.printStackTrace();
        }
    }

    public ConnectionStringInfo getConnectionStringFromName(String strDatabaseName)
    {
        for(ConnectionStringInfo conn : m_allConnectionConfiguration)
        {
            if(conn.isMatchDriver(strDatabaseName))
            {
                return conn.copyNew();
            }
        }
        return null;
    }

    public Connection connect(String strDatabaseName,String strUserName,String strPassword,String ...params)
        throws SQLException
    {
        for(ConnectionStringInfo conn : m_allConnectionConfiguration)
        {
            if(conn.isMatchDriver(strDatabaseName))
            {
                try
                {
                    Driver mydriver = (Driver) Class.forName(conn.getDriver()).newInstance();
                    DriverManager.registerDriver((Driver) mydriver);
                    return DriverManager.getConnection(conn.parseConnectionString(params),strUserName,strPassword);
                }
                catch(ClassNotFoundException excep)
                {
                    throw new SQLException("The Driver class [" + conn.getDriver() +
                                           "]Can not be found, please check you classpath. " + excep.getMessage());
                }
                catch(SQLException excep)
                {
                    throw excep;
                }
                catch(Exception excep)
                {
                    throw new SQLException("Driver class [" + conn.getDriver() + "] was failed to inilized." +
                                           excep.getMessage());
                }
            }
        }
        throw new SQLException("Can not get the driver for database named :" + strDatabaseName);

    }

    public ConnectionStringInfo getConnectionInfo(String strDatabaseName,String ...params)
        throws SQLException
    {
        for(ConnectionStringInfo conn : m_allConnectionConfiguration)
        {
            if(conn.isMatchDriver(strDatabaseName))
            {
                return new ConnectionStringInfo(strDatabaseName,
                                                conn.getDriver(),
                                                conn.parseConnectionString(params));
            }
        }
        return null;
    }
}
